<template>
  <div :class="`${prefixCls}`" isGroup="true">
    <Checkbox
      v-for="item in options"
      :key="item.value"
      :checked="checkedStatus.has(item.value)"
      :value="item.value"
      :disabled="item.disabled"
      @change="handleChange"
      >{{ item.label }}</Checkbox
    >
    <slot v-if="options.length === 0"></slot>
  </div>
</template>

<script>
import Checkbox from "./checkbox"; //导入多选框组件
export default {
  name: "CheckboxGroup",
  props: {
    prefixCls: {
      default: "em-checkbox-group",
      type: String,
    },
    defaultValue: {
      //默认选中的多选 value
      default: () => [],
      type: Array,
    },
    value: {
      default: undefined,
      type: Array,
    },
    options: {
      default: () => [],
      type: Array,
    },
  },
  model: {
    prop: "value",
  },
  data() {
    //是否传入默认选中的值
    const { value, defaultValue } = this;
    return {
      stateValue: value || defaultValue,
    };
  },
  computed: {
    checkedStatus() {
      //https://wiki.developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/Set
      return new Set(this.stateValue);
    },
  },
  created() {
    this.setChildCheckbox(this.$slots.default); //插槽是否存在状态
  },
  methods: {
    handleChange(event) {
      //多选框组是否选中函数
      if (this.disabled) {
        return false;
      }

      const target = event.target;
      const { value: targetValue, checked } = target;
      const { stateValue, value } = this;
      let newVal = [];
      if (checked) {
        newVal = [...stateValue, targetValue];
      } else {
        newVal = [...stateValue];
        const index = newVal.indexOf(targetValue);
        index >= 0 && newVal.splice(index, 1);
      }
      newVal = [...new Set(newVal)]; //观察者模式
      if (value === undefined) {
        this.stateValue = newVal;
      }
      this.$emit("input", newVal);
      this.$emit("change", newVal);
    },
    setChildCheckbox(children = []) {
      //group组件中使用其他组件
      const { options, $slots, checkedStatus } = this;
      if (options.length === 0 && $slots.default) {
        //如果有插槽有并且有数据时执行以下代码
        children.forEach(({ componentOptions = {}, children: newChildren }) => {
          const { Ctor, propsData } = componentOptions;
          if (Ctor && Ctor.options.name === "Checkbox") {
            propsData.isGroup = true;
            propsData.onGroupChange = this.handleChange;
            propsData.checked = checkedStatus.has(propsData.value);
          } else {
            this.setChildCheckbox(newChildren);
          }
        }, this);
      }
    },
  },
  mounted() {},
  beforeUpdate() {
    this.setChildCheckbox(this.$slots.default);
  },
  watch: {
    value(val) {
      this.stateValue = val;
      this.setChildCheckbox(this.$slots.default);
    },
  },
  components: {
    Checkbox,
  },
};
</script>
<style lang="scss" scoped>
@import "./main.scss";
</style>
